home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 24 / CU Amiga Magazine's Super CD-ROM 24 (1998)(EMAP Images)(GB)(Track 1 of 2)[!][issue 1998-07].iso / Scalos / RenderLib / doc / tutorial < prev    next >
Text File  |  1997-09-10  |  19KB  |  537 lines

  1.  
  2. tutorial
  3. -----------------------------
  4.  
  5.   this tutorial intends to generally explain basic terms of image
  6.   processing and to instruct the programming of render.library.
  7.  
  8.  
  9.  
  10. introduction
  11. -----------------------------
  12.  
  13.   render.library provides low-level image processing. there are no
  14.   functions implemented that interact with higher-level resources,
  15.   such as rastports or datatypes. you may call render.library an
  16.   image processing kernel.
  17.  
  18.   there's no reason for hesitation, though. i hope this tutorial
  19.   will help you to find the thread to image processing and
  20.   conversion. as you will see, the functions provided with
  21.   render.library are very easy to use, once you've understood the
  22.   basic terms, and most functions provide much more power and
  23.   functionality than it might appear at first sight.
  24.  
  25.  
  26.  
  27. philosophy
  28. -----------------------------
  29.  
  30.   function interfaces are kept lean and logical. first of all i
  31.   focused on using as few definitions as possible. you will notice
  32.   that you can use the majority of render.library's functions
  33.   without setting up a single structure. each function was reduced
  34.   to an absolute minimum of mandatory parameters. any argument that
  35.   in some way could be assigned a default value to has been made
  36.   optional and was banned to the taglists.
  37.  
  38.   render.library is layouted quasi object-oriented. everything is
  39.   kept in black boxes, and objects heavily interact internally, only
  40.   you don't know anything about the chemistry. many functions may be
  41.   interpreted as constructors, destructors and methods, only the
  42.   interfaces are implemented procedurally. there is nothing
  43.   available for misguiding, insane assumptions.
  44.  
  45.  
  46. overview
  47. -----------------------------
  48.  
  49.   render.library covers the following domains:
  50.  
  51.     > planar to chunky conversion
  52.  
  53.       and vice versa. the functions in this domain are considered
  54.       low-level, and they do not interact with higher-level
  55.       graphics.library instances such as rastports. you have to
  56.       take good care not to play havoc with non-standard bitmaps.
  57.       please read the appropriate autodoc chapters very carefully.
  58.  
  59.       - Planar2ChunkyA()
  60.       - Chunky2BitMapA()
  61.  
  62.  
  63.     > chunky to truecolor conversion
  64.  
  65.       this is a simple task, and render.library serves it with
  66.       high speed and flexibility. Amiga-specific modes (HAM6 and
  67.       HAM8) are correctly handled even with horizontal offsets.
  68.         
  69.       - Chunky2RGBA()
  70.  
  71.  
  72.     > palettes
  73.     
  74.       render.library uses a special type of color-lookup tables,
  75.       called 'palettes'. a render.library palette is much more
  76.       than a mere table of RGB values. all that nasty stuff is
  77.       hidden from you throughout these functions:
  78.  
  79.       - CreatePaletteA()
  80.       - ImportPaletteA()
  81.       - ExportPaletteA()
  82.       - SortPaletteA()
  83.  
  84.  
  85.     > histograms
  86.     
  87.       histograms are in most cases not more than a means to an
  88.       end. they are required for color reduction, statistics, and
  89.       for certain low-level functions. render.library supports
  90.       'real' truecolor histograms with up to 24bit resolution.
  91.       this feature is rarely found (and rarely needed, but
  92.       sometimes it cannot be dispensed).
  93.  
  94.       - CreateHistogramA()
  95.       - AddChunkyImageA()
  96.       - AddRGBImageA()
  97.       - AddRGB()
  98.       - AddHistogram()
  99.       - CountRGB()
  100.       - QueryHistogram()
  101.  
  102.  
  103.     > color reduction (quantization)
  104.     
  105.       this task is everything but trivial. render.library
  106.       uses a sophisticated algorythm that can stand the test
  107.       with the most-elaborated implementations on the Amiga
  108.       platform.
  109.  
  110.       - ExtractPaletteA()
  111.  
  112.  
  113.     > truecolor to chunky conversion (rendering)
  114.  
  115.       this task was the initial idea for render.library, and
  116.       render.library deserves its name. just have a look at all
  117.       those possible taglist arguments for
  118.       
  119.       - RenderA()
  120.  
  121.  
  122.     > chunky to chunky conversion
  123.         
  124.       this is similar to RenderA(), only that it accepts
  125.       chunky bytes as input.
  126.         
  127.       - ConvertChunkyA()
  128.       - CreatePenTableA()
  129.  
  130.  
  131.     > mapping
  132.     
  133.       in addition to those fully-featured rendering and
  134.       chunky-conversion functions, render.library offers a
  135.       low-level conversion class called mapping-engine.
  136.       
  137.       - CreateMapEngineA()
  138.       - MapChunkyArrayA()
  139.       - MapRGBArrayA()
  140.     
  141.  
  142.     > scaling
  143.     
  144.       render.library provides an own scaling class. its instances
  145.       are called scaling-engines. the performance of
  146.       non-interpolating scaling-engines comes close to CopyMem().
  147.       Scaling-engines may be passed to RenderA() and
  148.       ConvertChunkyA(), allowing scaling and rendering in a
  149.       single pass.
  150.  
  151.       - CreateScaleEngineA()
  152.       - ScaleA()
  153.       - ScaleOrdinate()
  154.  
  155.  
  156.     > alpha-channel
  157.  
  158.       this is a trivial task with render.library and can be
  159.       achieved with these functions:
  160.         
  161.       - InsertAlphaChannelA()
  162.       - ExtractAlphaChannelA()
  163.       - ApplyAlphaChannelA()
  164.       - MixRGBArrayA()
  165.  
  166.  
  167.     > memory management
  168.  
  169.       render.library features a lean and simple, but yet
  170.       effective memory management system throughout these
  171.       functions:
  172.         
  173.       - CreateRMHandlerA()
  174.       - AllocRenderMem()
  175.       - AllocRenderVec()
  176.  
  177.  
  178.  
  179. data types
  180. -----------------------------
  181.  
  182.   what kind of data can be processed with render.library?
  183.   currently, there are the following formats available:
  184.  
  185.     > PIXFMT_0RGB_32          (ULONG)
  186.  
  187.       longword truecolor pixels, with the sequence
  188.         
  189.       0x00rrggbb
  190.         
  191.       the upmost byte is not defined, and in most cases may
  192.       contain alpha-channel information.
  193.         
  194.     > PIXFMT_CHUNKY_CLUT      (UBYTE)
  195.         
  196.       chunky-byte pixels with color-lookup table. a pixel's
  197.       actual color is not defined throughout this format.
  198.       therefore you need a palette for most operations with
  199.       arrays of chunky bytes. usually, the byte value
  200.       acts directly as an index to the color-lookup table.
  201.  
  202.  
  203.   for certain operations, an additional specification is required
  204.   for the access to a color-lookup table:
  205.  
  206.     > COLORMODE_CLUT
  207.     
  208.       this mode defines 'normal' color lookup (see above). one
  209.       byte directly acts as an index to a color-lookup table.
  210.  
  211.     > COLORMODE_HAM6
  212.  
  213.       this mode defines HAM6 color lookup. one byte does not
  214.       necessarily reference a palette index.
  215.  
  216.     > COLORMODE_HAM6
  217.  
  218.       this mode defines HAM8 color lookup. one byte does not
  219.       necessarily reference a palette index.
  220.  
  221.   remember that COLORMODE_HAM6 and COLORMODE_HAM8 still apply to
  222.   chunky pixels, although HAM is an Amiga specific format that was
  223.   (unfortunately) never defined for chunky bytes, but rather for
  224.   planar data ('bitplanes').
  225.  
  226.  
  227.  
  228. memory management
  229. -----------------------------
  230.  
  231.   since image processing is in general quite hungry for memory
  232.   resources, render.library offers a both simple and effective
  233.   custom memory management.
  234.   
  235.   you don't need to use it, but it may help you to make things
  236.   easier and faster. under normal circumstances, you probably want
  237.   to set up a pooled memory environment. pooled memory helps to
  238.   avoid memory fragmentation, and it preserves the system's public
  239.   memory lists from too much stressing. create a pooled memhandler
  240.   as follows:
  241.  
  242.     memhandler = CreateRMHandler(RND_MemType, RMHTYPE_POOLED,
  243.      TAG_DONE);
  244.  
  245.   * note: pooled memory is not available prior to exec v39. if
  246.   not available, just create a 'standard' memory handler with
  247.   RMHTYPE_PUBLIC - the default value. if your project won't
  248.   include many large images, palettes and histograms, you
  249.   might as well create a 'standard' memory handler.
  250.  
  251.   you might even live without a memhandler, since the memhandler
  252.   argument is always optional - public memory will be used in
  253.   this case. nevertheless, i recommend to use a memhandler. it
  254.   helps you to easily upgrade your code to a more sophisticated
  255.   memory management when necessary. for the use with dynamic
  256.   histograms (see next section), a pooled memory handler is
  257.   highly advised.
  258.  
  259.   you may also set up a memory manager that operates in a static
  260.   block of memory. this is similar to the memory management of
  261.   programs like AdPro. they grab a large block of memory at
  262.   startup and allocate all intermediate buffers from this memory
  263.   area. example:
  264.  
  265.     memhandler = CreateRMHandler(RND_MemType, RMHTYPE_PRIVATE,
  266.         RND_MemBlock, my_memblock,
  267.         RND_MemSize, my_memblock_size, TAG_DONE);
  268.  
  269.   * note: private memory management is less flexible than a
  270.   pooled memory environment. once the static buffer is full or
  271.   becomes fragmented, further allocations will fail. v39 exec
  272.   pools will automatically grow and shrink to the required size.
  273.   
  274.   not only render.library functions may profit from a memhandler.
  275.   your application has access to it throughout these functions:
  276.  
  277.     mem = AllocRenderMem(memhandler, size);
  278.     FreeRenderMem(memhandler, mem, size);
  279.  
  280.     mem = AllocRenderVec(memhandler, size);
  281.     FreeRenderVec(mem);
  282.  
  283.   the main idea is to allow your application and render.library to
  284.   share a particular memory pool. this will keep the whole memory
  285.   management lean and effective.
  286.  
  287.  
  288.  
  289. histograms
  290. -----------------------------
  291.  
  292.   a histogram is an object that holds color information. it
  293.   maintains a counter for each color.
  294.  
  295.   many functions are related to histograms. their creation is
  296.   quite simple:
  297.  
  298.     histogram = CreateHistogram(RND_RMHandler, memhandler,
  299.                     RND_HSType, HSTYPE_15BIT_TURBO,
  300.                     TAG_DONE);
  301.  
  302.   render.library offers two different histogram schemes: the
  303.   _TURBO types are provided with tables, the 'normal' types use
  304.   digital trees. tabular histograms are very fast, but their
  305.   memory consumption is determined according to 2^bits x 4
  306.   bytes. with other words, a 12bit histogram is very small (8192
  307.   bytes), but a 24bit histogram would require 64mb of memory. it
  308.   would be nonsense to create a 24bit tabular histogram anyway,
  309.   since most images do not contain all possible RGB values. that's
  310.   why _TURBO histograms are limited to 12, 15, and 18 bit
  311.   resolution.
  312.  
  313.   tree histograms are more flexible. their memory consumption is
  314.   not predictable, because they are created dynamically. a
  315.   drawback is that every single RGB entry in a tree histogram
  316.   requires 20 bytes of memory. the tree type allows you to create
  317.   'real' histograms with full 24bit accuracy. by the way, this is
  318.   the only way to evaluate the effective number of different
  319.   colors in an image. (most image processing applications operate
  320.   with 15bit histograms and tell you nonsense about the number of
  321.   colors found.)
  322.  
  323.   * a 15 bit _TURBO histogram is the best choice in most cases.
  324.   as mentioned before, most image processing applications use
  325.   this resolution. render.library histograms are interpolated.
  326.   this reasonably compensates the loss of information.
  327.   
  328.   now that we've created a histogram, what are we going to do with
  329.   it? first of all, we have to load it with color information.
  330.  
  331.     success = AddRGBImage(histogram, rgb_array, 
  332.                                 640, 480, NULL);
  333.  
  334.   in this example, a 640×480 truecolor image is added to the
  335.   histogram. you may of course add as many pictures as you like,
  336.   e.g. in order to record all the single frames of an animation.
  337.   it's also possible to directly add chunky images to a histogram:
  338.  
  339.      success = AddChunkyImage(histogram, chunky_array, 640, 480,
  340.             palette, NULL);
  341.  
  342.   (as you can see, chunky images require a palette. palettes will
  343.   be covered by the next chapter.)
  344.  
  345.   * note: the return value <success> is not boolean, it's
  346.   defined with constants. you must check for ADDH_SUCCESS, since
  347.   adding data to histograms may fail at any time. your histogram
  348.   won't be corrupted in that case, but if you don't check the
  349.   return value, you can't depend on finding your histogram in a
  350.   state that correctly represents the data you've added.
  351.   
  352.   you can find out about certain histogram parameters with the
  353.   QueryHistogram() function. for instance
  354.  
  355.     number_of_pixels = QueryHistogram(histogram, RND_NumPixels);
  356.     number_of_colors = QueryHistogram(histogram, RND_NumColors);
  357.  
  358.   another way to access histograms is the CountRGB() function. it
  359.   returns the number of pixels recorded for a specific RGB value:
  360.  
  361.     pixels_represented = CountRGB(histogram, 0x00rrggbb);
  362.  
  363.   * note: according to current definitions, histograms can hold
  364.   the information for 2^32 (4,28 billions) pixels. as long as no
  365.   overflow occurs to a single entry inside the histogram, they
  366.   may even contain 2^32 different colors. further
  367.   histogram-related processing (e.g. quantization) is defined
  368.   for 2^32 pixels, though.
  369.  
  370.  
  371.  
  372. palettes
  373. -----------------------------
  374.  
  375.   most functions dealing with chunky pixels require color-lookup
  376.   tables. in the context of render.library, they are called
  377.   'palettes'. palettes cover many technical details internally.
  378.   a palette is created this way:
  379.  
  380.     palette = CreatePalette(NULL);
  381.  
  382.   this sets up a palette of 15bit resolution. these 15bit suffice
  383.   in most situations, and they are taken into account only if some
  384.   kind of rendering or mapping takes place. more control can be
  385.   obtained via taglist arguments:
  386.  
  387.     palette = CreatePalette(RND_HSType, HSTYPE_12BIT, TAG_DONE);
  388.  
  389.   as you can see, a palette's resolution is specified analogously
  390.   to a histogram's resolution.
  391.   
  392.   * note: palettes do not differenciate between _TURBO and
  393.   non-TURBO types.
  394.   
  395.   in addition to that, you can supply CreatePalette() with a
  396.   memhandler (which is not a bad idea at all):
  397.  
  398.     palette = CreatePalette(RND_RMHandler, memhandler, TAG_DONE);
  399.  
  400.   after all, what you get is just an empty palette ready for being
  401.   loaded with colors. by default, ImportPaletteA() handles
  402.   0x00rrggbb color entries. you may as well import LoadRGB32-alike
  403.   and LoadRGB4-type tables.
  404.  
  405.     ULONG colortable[5] =
  406.         {0xff0088, 0x007532, 0x435278, 0xffffff, 0x000000};
  407.  
  408.     ImportPalette(palette, colortable, 5, NULL);
  409.  
  410.   you may import colors mulitple times and specify
  411.   offsets:
  412.  
  413.     ImportPalette(palette, colortable1, 10, NULL);
  414.     ImportPalette(palette, colortable2, 20, RND_NewPalette, FALSE,
  415.         RND_FirstColor, 10, TAG_DONE);
  416.  
  417.   with RND_NewPalette set to FALSE, ImportPaletteA() merges
  418.   color entries to a palette. the RND_FirstColor tag specifies
  419.   the offset where to add new colors. the total number of
  420.   colors in a palette is automatically maintained and updated.
  421.   the only restriction is that you are neither allowed to
  422.   import more than 256 colors, nor to import beyond the 256th
  423.   entry. the counterpart of ImportPaletteA() is
  424.   ExportPaletteA().
  425.  
  426.   another way to load a palette with colors is via
  427.   ExtractPaletteA() - refer to the next section.
  428.  
  429.  
  430.  
  431. quantization
  432. -----------------------------
  433.  
  434.   i've got you here, right? quantization ('color reduction') is
  435.   extremely easy with render.library. you just have to supply a
  436.   source histogram and a destination palette.
  437.  
  438.     success = ExtractPalette(histogram, palette, numcolors, NULL);
  439.  
  440.   this is the basic function call. it will extract the given
  441.   number of colors from the histogram and insert it into the
  442.   palette. refer to the autodocs for further details.
  443.  
  444.  
  445.  
  446. rendering
  447. -----------------------------
  448.  
  449.   now for the climax of it all and to what gave render.library its
  450.   name. let's transform a RGB array to chunky pixels:
  451.  
  452.     success = Render(rgbarray, width, height, chunkyarray,
  453.                 palette, tags);
  454.  
  455.   there are many tags available, for dithering, offsets, secondary
  456.   conversions, HAM mode support, scaling, callback hooks, and
  457.   more. the same applies to the chunky-byte equivalent:
  458.  
  459.     success = ConvertChunky(sourcearray, sourcepalette,
  460.         width, height, destarray, destpalette, tags);
  461.  
  462.   no need to mention that these functions are quite fast. if
  463.   they're still not fast enough for your purposes, refer to the
  464.   next section.
  465.  
  466.  
  467.  
  468. mapping
  469. -----------------------------
  470.  
  471.   you are disappointed by the speed of Render(), because it is
  472.   only several times faster than any other software on the Amiga?
  473.   then you have to enter the wonderful realm of mapping-engines.
  474.   mapping-engines focus on three aspects: a) speed, b) speed, c)
  475.   speed.
  476.   
  477.   * mapping-engines depend on a destination palette. The
  478.   contents of that destination palette may change, but it must
  479.   not be deleted prior to dependent mapping-engines.
  480.   
  481.   the mapping-engine may additionally depend on a histogram
  482.   containing the color information of those pixels that are
  483.   going to be mapped. this histogram has to be of a _TURBO
  484.   type of the same resolution as the palette. if there's a
  485.   histogram available that fits these specifications, you
  486.   are strongly recommended to use it¹. this improves speed
  487.   remarkably.
  488.  
  489.     mapengine = CreateMapEngine(destpalette, NULL);
  490.  
  491.     mapengine =
  492.         CreateMapEngine(destpalette, RND_Histogram, histogram,
  493.         TAG_DONE);
  494.  
  495.   now there are two ways of using a mapping-engine. the
  496.   preferrable way is to pass it to RenderA() or ConvertChunkyA()
  497.   with the RND_MapEngine tag argument. if you can manage without
  498.   dithering, scaling, callback hooks and alike, you might as well
  499.   use it with these functions:
  500.  
  501.     MapRGBArray(mapengine, rgbarray, width, height, chunkyarray,
  502.     tags);
  503.  
  504.     MapChunkyArray(mapengine, sourcearray, sourcepalette, width,
  505.     height, destarray, tags);
  506.  
  507.   the above functions have got very low overhead and provide
  508.   rather primitive data transfer schemes. MapRGBArrayA() comes
  509.   close to physical bus performance (with totally 4 memory
  510.   accesses per pixel).
  511.   
  512.   * a drawback with MapRGBArrayA() is that your RGB pixels may not
  513.   contain a trailing alphachannel-byte. it must by set to zero,
  514.   otherwise you must use RenderA() instead.
  515.   
  516.   a call to a function with a mapping-engine can be quite slow
  517.   when invoked for the first time (or whenever the destination
  518.   palette changed). the mapping-engine's internal buffers have
  519.   to be (re-)constructed then. that's where the optional
  520.   histogram gets into action: only those RGB values actually
  521.   appearing in the histogram are updated. if no histogram was
  522.   specified with CreateMapEngineA(), a mapping-table will be
  523.   calculated for the whole RGB space. the palette's resolution
  524.   is a significant factor then: a 12bit RGB space holds 4096
  525.   colors, a 15bit RGB space has got 32768 colors, and a 18bit
  526.   RGB space contains 262144 colors. you better know what you're
  527.   doing when creating a mapping-engine for a 18bit palette and
  528.   do not specify a histogram.
  529.  
  530.   * ¹note: nothing serious happens if the supplied histogram
  531.   does not correctly represent the data you convert with a
  532.   mapping-engine. however, colors that are not part of the
  533.   histogram would be mapped to nonsense pixels. unfortunately
  534.   this applies to conversions with dithering. you should
  535.   disable dithering when histogram-related mapping-engines are
  536.   passed to RenderA() or ConvertChunkyA().
  537.